/*
 * 易族智汇（北京）科技有限公司 版权所有。
 * 未经许可，您不得使用此文件。
 * 官方地址：www.javamall.com.cn
 */
package com.enation.app.javashop.handler;

import com.enation.app.javashop.framework.security.sign.SignAspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 安全处理切面
 *
 * @author kingapex
 * @version 1.0
 * @data 2021/11/22 19:42
 **/
@Aspect
@Component
public class SecurityAspect {

    @Pointcut("execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.insert(..))")
    public void insert() {
    }

    @Pointcut("execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.updateById(..))")
    public void updateById() {
    }

    @Pointcut("execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.update(..))")
    public void update() {
    }

    @Pointcut("execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.selectById(..))")
    public void selectById() {
    }

    @Pointcut("execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.selectOne(..))")
    public void selectOne() {
    }

    @Pointcut("execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.selectPage(..))")
    public void selectPage() {
    }

    @Pointcut("execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.selectList(..))")
    public void selectList() {
    }


    @Autowired
    private SignAspect signAspect;

    @Autowired
    private DbAspect dbAspect;


    /**
     * 分页查询的处理，只需要对数据进行加解密，不处理签名
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("selectPage()")
    public Object aroundSelectPage(ProceedingJoinPoint point) throws Throwable {

        return dbAspect.aroundSelectPage(point);
    }


    /**
     * 列表查询，只需要对数据进行加解密，不处理签名
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("selectList()")
    public Object aroundSelectList(ProceedingJoinPoint point) throws Throwable {
      return dbAspect.aroundSelectList(point);
    }

    /**
     * 读取单行记录：
     * 需要先进行验签，再进行加解密操作
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("selectOne()")
    public Object aroundSelectOne(ProceedingJoinPoint point) throws Throwable {
        Object entity = point.proceed();
        //先进行验签操作
        signAspect.aroundSelectOne(entity);


        //验签后再进行加解密，否则之后验签会对明文进行验签的情况了
        dbAspect.aroundSelectOne(entity);

        return entity;
    }

    /**
     * 读取单行记录：
     * 需要先进行验签，再进行加解密操作
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("selectById()")
    public Object aroundSelectById(ProceedingJoinPoint point) throws Throwable {
        Object entity = point.proceed();
        //先进行验签操作
        signAspect.aroundSelectById(entity);


        //验签后再进行加解密，否则之后验签会对明文进行验签的情况了
        dbAspect.aroundSelectById(entity);
        return entity;
    }

    /**
     * 拦截update方法
     * 更新方法，需要先加密，之后再对密文签名
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("update()")
    public Object aroundUpdate(ProceedingJoinPoint point) throws Throwable {

        //先加密，再签名
        dbAspect.aroundUpdate(point);

        //在签名的方法中操作数据库，因为可能需要批量更新改为多次更新
        return signAspect.aroundUpdate(point);

    }

    /**
     * 拦截updateById方法
     * 更新方法，需要先加密，之后再对密文签名
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("updateById()")
    public Object aroundUpdateById(ProceedingJoinPoint point) throws Throwable {

        //先加密，再签名
        dbAspect.aroundUpdateById(point);

        //签名，并执行更新操作
        Object object = signAspect.aroundUpdateById(point);
        return object;
    }

    /**
     * 拦截insert方法
     * 更新方法，需要先加密，之后再对密文签名
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("insert()")
    public Object aroundInsert(ProceedingJoinPoint point) throws Throwable {
        Object[] args = point.getArgs();

        Object entity = args[0];
        //先加密，再签名
        dbAspect.aroundInsert(entity);
        signAspect.aroundInsert(entity);
        return point.proceed();
    }
}
